package io.github.bigbird0101.datatransfer.record.parse;


import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import integration.modle.exception.IntegrationValidException;
import integration.utils.AssertUtils;
import io.github.bigbird0101.datatransfer.model.element.*;
import io.github.bigbird0101.datatransfer.model.param.ColumnParameters;
import io.github.bigbird0101.datatransfer.record.Record;
import io.github.bigbird0101.datatransfer.record.RecordSender;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

import static io.github.bigbird0101.datatransfer.constants.Constant.*;

/**
 * 解析源端数据
 */
@Slf4j
@Data
@AllArgsConstructor
@NoArgsConstructor
public class RecordParse {

    // 字段
    protected List<ColumnParameters> columns;
    // 数据字段数量
    private int columnNumber;
    // 解析方式 split, json
    private String parseType;

    // parseType 为split
    private String split;


    public Record buildOneRecord(String value, RecordSender recordSender) {
        Record record = null;
        if (PARSE_TYPE_JSON.equalsIgnoreCase(parseType)) {
            record = parseJson(value, recordSender);
        } else if (PARSE_TYPE_SPLIT.equalsIgnoreCase(parseType)) {
            record = parseSplit(value, recordSender);
        }
        log.debug("record:{}", record.toString());

        return record;
    }

    private Record parseSplit(String value, RecordSender recordSender) {
        Record record = recordSender.createRecord();
        AssertUtils.isTrue(StrUtil.isNotBlank(value), "数据为空,识别为脏数据");
        String[] splits = value.split(this.split);
        if (splits.length != columnNumber) {
            // 实际消息字段数和配置字段数不一致
            String msg = String.format("源头读取字段列数%s与目标端字段写入列数%s不相等", splits.length, columnNumber);
            throw new IntegrationValidException(msg);
//            return null;
        }
        return parseColumns(Arrays.asList(splits), record);
    }

    /**
     * @param value
     * @param recordSender
     * @return
     */
    private Record parseJson(String value, RecordSender recordSender) {
        log.debug("parseJson value :{}", value);
        Record record = recordSender.createRecord();
        JSONObject jsonObject = JSONUtil.parseObj(value);
        List<String> datas = new ArrayList<>();
        for (ColumnParameters column : columns) {
            // 支持路径获取，job.name; column[0].name
            String dataVal = jsonObject.getByPath(column.getName(), String.class);
            datas.add(dataVal);
        }
        // 所有字段为空，则认为数据是脏数据
        long count = datas.stream().filter(Objects::isNull).count();
        log.debug("datas:{}, count:{}", datas, count);
        AssertUtils.isTrue(count != datas.size(), "所有字段值都是null,识别为脏数据");

        parseColumns(datas, record);
        return record;
    }


    private Record parseColumns(List<String> datas, Record record) {
        Map<String, String> meta = new HashMap<>();
        for (int i = 0; i < columns.size(); i++) {
            ColumnParameters columnParameters = columns.get(i);
            Column column = toColumn(datas.get(i), columnParameters.getType());
            // 记录每一行数据原始类型，用于不知道数据类型的目标端，例如json
            meta.put(i + "", columnParameters.getType());
            record.addColumn(column);
        }
        record.setMeta(meta);
        return record;
    }


    private Column toColumn(String value, String columnType) {
        switch (columnType.toLowerCase()) {
            case DATA_TYPE_BOOL:
                return new BoolColumn(value);
            case DATA_TYPE_INT:
                return new LongColumn(value);
            case DATA_TYPE_FLOAT:
                return new DoubleColumn(value);
            case DATA_TYPE_STRING:
            case DATA_TYPE_LIST_INT:
            case DATA_TYPE_LIST_STRING:
            case DATA_TYPE_LIST_FLOAT:
            case DATA_TYPE_LIST_BOOL:
            case DATA_TYPE_LIST_ANY:
            default:
                return new StringColumn(value);
        }
    }


}
